package com.pai4j.netty.server.common;


import org.apache.commons.collections.MapUtils;
import org.springframework.util.Assert;

import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 配置加载器
 */
public class PropertyLoader {

    public static final Map<String, Object> PROPERTIES = new ConcurrentHashMap<>();

    private static String PROPERTIES_FILE_PATH = "config/application-%s.properties";

    /**
     * 初始化配置
     *
     */
    public static void init() {
        try {
            new PropertyLoader().preLoadProperties();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("配置文件预加载失败！");
        }
    }

    /**
     * 配置对象销毁
     *
     */
    public static void destroy() {
        PROPERTIES.clear();
    }

    /**
     * 预加载配置
     *
     * @throws Exception
     */
    public void preLoadProperties() throws Exception {

        // 获取当前服务启动环境配置
        String env = System.getProperty("env");
        // 获取对应环境配置文件路径
        String propertiesFilePath = String.format(PROPERTIES_FILE_PATH, env);
        // 通过类加载器读取文件流
        InputStream is = PropertyLoader.class.getClassLoader().getResourceAsStream(propertiesFilePath);
        // 处理文件流转为Properties
        Properties properties = new Properties();
        properties.load(is);
        properties.forEach((k, v) -> {
            PROPERTIES.put(k.toString(), v);
        });
    }

    /**
     * 读取当前环境下的配置
     *
     * @param key
     * @return
     */
    public static Object getProperty(String key) {
        if (MapUtils.isEmpty(PROPERTIES)) {
            init();
        }
        return PROPERTIES.get(key);
    }

    /**
     * 安全的读取当前环境下的配置
     *
     * @param key
     * @return
     */
    public static <T> T safeGetProperty(String key, Class<T> clazz, boolean ... allowNull) {
        Object property = getProperty(key);
        if (property == null) {
            return null;
        }
        if (allowNull == null || allowNull.length == 0 || !allowNull[0]) {
            Assert.notNull(property, String.format("[%s] property must not null!", key));
        }
        String propertyVal = property.toString();
        if (clazz == Integer.class) {
            return (T) Integer.valueOf(propertyVal);
        } else if (clazz == Float.class) {
            return (T) Float.valueOf(propertyVal);
        } else if (clazz == Double.class) {
            return (T) Double.valueOf(propertyVal);
        } else if (clazz == Boolean.class) {
            return (T) Boolean.valueOf(propertyVal);
        }
        return (T) propertyVal;
    }
}
